﻿#include "devopt.h"
#include <Windows.h>
#include <process.h>
#include <TlHelp32.h>
#include <WinBase.h>
#include <string.h>

#include <QProcess>
#include <QHostAddress>
#include <QUdpSocket>
#include <QChar>
#include <QTextCodec>
#include <QDebug>


DevOpt::DevOpt()
{

}


bool DevOpt::actionCmd(QString cmd, QString &execStr, int msecs)
{
    bool ret = false;

    QProcess exc;
    QTextCodec *codec = QTextCodec::codecForName("GBK");

    exc.start(cmd);
    ret = exc.waitForFinished(msecs);
    execStr = codec->toUnicode(exc.readAllStandardError());

    return ret;
}

bool DevOpt::chkIsMacAddr(QString mac)
{
    QString macTmp = mac.contains(":") ? mac.split(":").join("-") : mac;
    QRegExp reg("^[a-z0-9]{2}");
    QStringList macSplitList = macTmp.split("-");
    bool isMatch = true;

    if(macSplitList.length() != 6)
    {
        return false;
    }

    foreach (QString macSplitStr, macSplitList)
    {
        if(!reg.exactMatch(macSplitStr))
        {
            isMatch = false;
            break;
        }
    }

    return isMatch;
}

QString DevOpt::closePc(CLOSE_PC_TYPE type, QString argv)
{
    QString cmd("");

    switch (type)
    {
    case CLOSE_PC_AT_ONCE: // 关机
        cmd = "shutdown -p -f"; // shutdown -s -t 0
        break;
    case CLOSE_PC_BY_TIME: // 定时关机
        cmd = QString("at %1 Shutdown -p -f").arg(argv);
        break;

    case RESTART_PC_AT_ONCE: // 立即重启
        cmd = "shutdown -r -f";
        break;

    case RESTART_PC_BY_TIME: // 定时重启
        cmd = QString("at %1 Shutdown –r -f").arg(argv);
        break;

    case SLEEP_PC_AT_ONCE: // 系统休眠
        cmd = "shutdown -h -f";
        break;

    case LOGOFF_PC_AT_ONCE: // 注销
        cmd = "shutdown -l -f";
        break;

    case REMOVE_CLOSE_PC: // 远程关机
        cmd = QString("shutdown -s -m \\\\%1 -t 1 -f").arg(argv);
        break;
    }

    return cmd;
}


bool DevOpt::closePcByWinApi()
{
    HANDLE hToken;
    TOKEN_PRIVILEGES tkp;

    //获取进程标志
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
        return false;

    //获取关机特权的LUID
    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,    &tkp.Privileges[0].Luid);
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    //获取这个进程的关机特权
    AdjustTokenPrivileges(hToken, false, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
    if (GetLastError() != ERROR_SUCCESS) return false;

    // 强制关闭计算机
    if ( !ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0))
        return false;
    return true;
}

bool DevOpt::closePcByCmd()
{
    QString cmd = closePc(CLOSE_PC_AT_ONCE);
    QString ret("");
    return actionCmd(cmd, ret);
}


bool DevOpt::openPc(QString macStr, QString addr)
{
    /*到达此处说明mac地址是正确的,且默认分割符为“-”，此处只执行开机操作*/
    const int PORT = 6;
    bool ok = false;
    unsigned char mac[6];
    unsigned char magicPacket[102];
    int macBit = 0;

    QUdpSocket *sender = new QUdpSocket();

    foreach (QString macSplitText, macStr.split("-"))
    {
        mac[macBit] = static_cast<unsigned char>(macSplitText.toInt(&ok, 16));
        macBit++;
    }

    for(int magicPacketHead = 0; magicPacketHead < 6; magicPacketHead++)
    {
        magicPacket[magicPacketHead] = 0xFF;
    }

    for(int magicPacketHead = 1; magicPacketHead < 17; magicPacketHead++)
    {
        for(int magicPacketTail = 0; magicPacketTail < 6; magicPacketTail++)
        {
            magicPacket[magicPacketHead * 6 + magicPacketTail] = mac[magicPacketTail];
        }
    }

    QHostAddress serverAddress = QHostAddress(addr);
    sender->writeDatagram(reinterpret_cast<char*>(magicPacket), sizeof(magicPacket), serverAddress, PORT);

    delete sender;
    return true;
}

bool DevOpt::openSoft(QString softname)
{
    QProcess pro;
    return pro.startDetached(softname);
}

bool DevOpt::closeSoft(QString softname)
{
    const char *filename = (char*)softname.data();
    HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
    PROCESSENTRY32 pEntry;
    pEntry.dwSize = sizeof (pEntry);
    BOOL hRes = Process32First(hSnapShot, &pEntry);
    while (hRes)
    {
        if (strcmp((char*)pEntry.szExeFile, filename) == 0)
        {
            HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0,
                                          (DWORD) pEntry.th32ProcessID);
            if (hProcess != NULL)
            {
                TerminateProcess(hProcess, 9);
                CloseHandle(hProcess);
            }
        }
        hRes = Process32Next(hSnapShot, &pEntry);
    }
    CloseHandle(hSnapShot);

    return true;
}

bool DevOpt::closeSoftByCmd(QString softname)
{
    /* taskkill /f /t /im */
    QString cmd = QString("taskkill /f /t /im %1").arg(softname);
    QString ret;
    return actionCmd(cmd, ret);
}

